之前因为时间紧迫的缘故,在公司的CentOS 7 机器上部署一个快速实现的数据收集工具,考虑到避免其他语言发布和变更起来麻烦,于是就用 python+bash 实现。
服务端就是最简单不引入任何python包的SimpleHTTPServer+Handler实现的。
偶然一次看日志发现本来应该在三分钟内完成的一个同步/上报循环结果未能如期完成,每个请求看起来相隔十秒左右,最后定位下来是python2.6.6的问题。
简单起见,我用下面重现一下: 10.135.20.45上开了一个进程
python -m SimpleHTTPServer 12888
在另外一台机器上
|
|
这里两个问题:
1)一个简单的GET请求耗时10秒,10秒看起来像是服务器设置的超时时间。
2)而且10秒都花费在 starttransfer
如何定位问题?显然逐步打点耗时是可以的,但是如果用搜索引擎更快,我在python社区上找到一个提问,作者遇到同样现象,但是pytohn2.7以后就没有问题。
有个回答说是 pytohn解析header时候\r\n的问题,也有说是socket未close问题,我看了下代码,不像。
不过这个提问给了我思路,于是我比较了python 2.6/2.7各自的SimpleHTTPServer.py文件。
考虑到linux版本众多且你可能也记不住,友情提示一个定位该文件的方法:
|
|
一般就在 /usr/lib64/python2.6/ 下面了。
不过2.6/2.7的SimpleHTTPServer.py没有明显差异,继续再比对他们的父类:BaseHTTPServer.py
下图简单列下不同点。
时间问题,直接上答案,问题就出在log_message里,python原意只是记录response的相关结果,但没想到会成为耗时的元凶:
我在该机器上跑一下,发现却是是耗费10秒
time python -c 'import socket; print socket.getfqdn()'
python 2.7 之后就改过来了,不再适用 address_string,所以在现代服务器上不会出现上述问题。
getfqdn为什么会耗时呢?这和pyhon hostname 解析实现相关,后续可分享一下。
以上简单记录遇到的问题,读者可留意。解决方法其实可以替换python的BaseHTTPServer.py,也可以自己拷贝出来一份修改,但说到底不如正规的方案去实现。
后记:
getfqdn 底层调用的就是 socket.gethostbyaddr() – map an IP number or hostname to DNS info
(生产环境配置 域名/反向域名解析服务)
另 socket.py